<?php
/**
 * PDO连接处理类
 *
 * @author ananda
 */
class Connection_Pdo extends Connection_Base
{
    /**
     * 是否开启调试模式
     * @var <boolean> 
     */
    public static $debug_mode = false;

    /**
     * 使用过的查询申明
     * @var <array>
     */
    protected $statements = array();

    /**
     * 连接驱动创建及初始化
     */
    public function init()
    {
        $host    = $this->conf['host'];
        $port    = isset($this->conf['port'])    ? $this->conf['port']   : null;
        $dbname  = isset($this->conf['dbname'])  ? $this->conf['dbname'] : null;
        $options = isset($this->conf['options']) ? $this->conf['options'] : null;

        $dsn = "{$this->conf['type']}:host=$host";
        $port   && ($dsn .= ";port=$port");
        $dbname && ($dsn .= ";dbname=$dbname");

        $this->driver = new PDO($dsn, $this->conf['user'], $this->conf['passwd'], $options);

        //可视情况是否启用
        isset($this->conf['charset']) && $this->setCharset();
    }

    /**
     * 设置数据库字符集
     * 仅工作在mysql下
     *
     * @param <string> $charset
     */
    public function setCharset($charset = null)
    {
        $charset && ($charset = $this->conf['charset']);
        return $this->driver->exec("set names '{$dsn_conf['charset']}'");
    }

    public function read($sql, $bind = array(), $options = array())
    {
        $statement = $this->execute($sql, $bind, $options);
        if (Error::is($statement)) {
            return $statement;
        }
        return $this->buildResult('Data_Collection_Pdo', $statement, $options);
    }

    public function readOne($sql, $bind = array(), $options = array())
    {
        $statement = $this->execute($sql, $bind, $options);
        if (Error::is($statement)) {
            return $statement;
        }
        return $this->buildResult('Data_Record_Pdo', $statement, $options);
    }

    public function create($sql, $bind = array(), $options = array())
    {
        return $this->execute($sql, $bind, $options);
    }

    public function update($sql, $bind = array(), $options = array())
    {
        return $this->execute($sql, $bind, $options);
    }

    public function delete($sql, $bind = array(), $options = array())
    {
        return $this->execute($sql, $bind, $options);
    }

    public function exec($sql)
    {
        return $this->driver->exec($sql);
    }

    protected function execute($sql, $bind = array(), $options = array())
    {
        $statement_key = md5($sql);
        if (!isset($this->statements[$statement_key])) {
            $driver_options = isset($options['driver_options']) ? $options['driver_options'] : array();
            $this->statements[$statement_key] = $this->driver->prepare($sql, $driver_options);
        }

        $statement = $this->statements[$statement_key];
        isset($options['fetch_mode']) && $statement->setFetchMode($options['fetch_mode']);

        foreach ($bind as $key => $value) {
            $statement->bindValue($key, $value);
        }

        if (self::$debug_mode) {

            Com::dump($bind, 'Bind Values');
            Com::dump($statement->queryString, 'Sql Pattern');
            echo "<pre>";
            $statement->debugDumpParams();
            die();

        } else {

            $result = $statement->execute();

        }

        if (!$result) {
            $error_info = $this->driver->errorInfo();
            $error_info = 'Pdo error['.$error_info[0].']: '.$error_info[1].' | '.$error_info[2];
            return new Error($error_info);
        }
        return $statement;
    }

    public function replaceParams($sql, $params = array(), $quote = false)
    {
        foreach ($params as $key => $value) {
            $sql = str_replace(":$key", $quote ? $this->quote($value) : $value, $sql);
        }
        return $sql;
    }

    public function beginTransaction()
    {
        return $this->driver->beginTransaction();
    }

    public function rollBack()
    {
        return $this->driver->rollBack();
    }

    public function commit()
    {
        return $this->driver->commit();
    }

    public function quote($string, $parameter_type = PDO::PARAM_STR)
    {
        return $this->driver->quote($string, $parameter_type);
    }

    public function lastInsertId($name = null)
    {
        return $this->driver->lastInsertId($name);
    }

    public function close()
    {
        unset($this->driver);
        return true;
    }
}
?>